🎖️GitЯра🎖️
Node / meshtastic / Meshtastic-Android / files / core / service / src / androidMain / kotlin / org / meshtastic / core / service / AndroidNotificationManager.kt
Displaying Raw • Download
core/service/src/androidMain/kotlin/org/meshtastic/core/service/AndroidNotificationManager.kt 2d20cd8a4708e2ef66e98d5259f3a97ec93f240a (2d20cd8a) Text, 8.74 KB
T8b949e/*
* Copyright (c) 2026 Meshtastic LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
Tff7b72package T7ee787org.meshtastic.core.service
Tff7b72import T7ee787android.app.NotificationChannel
Tff7b72import T7ee787android.app.PendingIntent
Tff7b72import T7ee787android.app.TaskStackBuilder
Tff7b72import T7ee787android.content.Context
Tff7b72import T7ee787android.content.Intent
Tff7b72import T7ee787android.os.Build
Tff7b72import T7ee787androidx.core.app.NotificationCompat
Tff7b72import T7ee787androidx.core.app.NotificationManagerCompat
Tff7b72import T7ee787androidx.core.content.getSystemService
Tff7b72import T7ee787androidx.core.net.toUri
Tff7b72import T7ee787org.koin.core.annotation.Single
Tff7b72import T7ee787org.meshtastic.core.repository.Notification
Tff7b72import T7ee787org.meshtastic.core.repository.NotificationManager
Tff7b72import T7ee787org.meshtastic.core.resources.R.drawable
Tff7b72import T7ee787org.meshtastic.core.resources.Res
Tff7b72import T7ee787org.meshtastic.core.resources.getString
Tff7b72import T7ee787org.meshtastic.core.resources.meshtastic_alerts_notifications
Tff7b72import T7ee787org.meshtastic.core.resources.meshtastic_low_battery_notifications
Tff7b72import T7ee787org.meshtastic.core.resources.meshtastic_mesh_beacon_notifications
Tff7b72import T7ee787org.meshtastic.core.resources.meshtastic_messages_notifications
Tff7b72import T7ee787org.meshtastic.core.resources.meshtastic_new_nodes_notifications
Tff7b72import T7ee787org.meshtastic.core.resources.meshtastic_service_notifications
Tff7b72import T7ee787android.app.NotificationManager Tff7b72as Te6edf3SystemNotificationManager
Tf0883e@Single
Tff7b72class T56d364AndroidNotificationManagerTb4b4b4(Tff7b72private Tff7b72val Te6edf3contextTb4b4b4: Te6edf3ContextTb4b4b4) Tb4b4b4: Te6edf3NotificationManager Tb4b4b4{
Tff7b72private Tff7b72val Te6edf3notificationManager Tff7b72=
Te6edf3checkNotNullTb4b4b4(Te6edf3contextTb4b4b4.Te6edf3getSystemServiceTff7b72<Te6edf3SystemNotificationManagerTff7b72>Tb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{ Ta5d6ff"Ta5d6ffNotificationManager not foundTa5d6ff" Tb4b4b4}
Tff7b72private Tff7b72data Tff7b72class T56d364ChannelConfigTb4b4b4(Tff7b72val Te6edf3idTb4b4b4: Tffa657StringTb4b4b4, Tff7b72val Te6edf3importanceTb4b4b4: Tffa657IntTb4b4b4)
T8b949e/**
* Tracks whether notification channels have been created.
*
* Channels are **not** created in the constructor because this singleton is instantiated by Koin during
* [org.meshtastic.core.service.MeshService.onCreate] on the main thread. The CMP [getString] helper uses
* [kotlinx.coroutines.runBlocking] which can fail in that context, crashing the entire service startup chain.
* Instead, channels are lazily ensured before the first [dispatch] call. Note that
* [MeshNotificationManagerImpl.initChannels] already creates a superset of these channels when the orchestrator
* starts, so this lazy path is only a safety net for notifications dispatched before orchestrator initialization.
*/
Tff7b72private Tff7b72var Te6edf3channelsInitialized Tff7b72= Tff7b72false
Tff7b72private Tff7b72fun Td2a8ffensureChannelsInitializedTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3channelsInitializedTb4b4b4) Tff7b72return
Te6edf3channelsInitialized Tff7b72= Tff7b72true
Tff7b72if Tb4b4b4(Te6edf3BuildTb4b4b4.Te6edf3VERSIONTb4b4b4.Te6edf3SDK_INT Tff7b72>Tff7b72= Te6edf3BuildTb4b4b4.Te6edf3VERSION_CODESTb4b4b4.Te6edf3OTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3channels Tff7b72=
Te6edf3listOfTb4b4b4(
Te6edf3createChannelTb4b4b4(Te6edf3NotificationTb4b4b4.Te6edf3CategoryTb4b4b4.Te6edf3MessageTb4b4b4, Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3meshtastic_messages_notificationsTb4b4b4)Tb4b4b4,
Te6edf3createChannelTb4b4b4(Te6edf3NotificationTb4b4b4.Te6edf3CategoryTb4b4b4.Te6edf3NodeEventTb4b4b4, Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3meshtastic_new_nodes_notificationsTb4b4b4)Tb4b4b4,
Te6edf3createChannelTb4b4b4(Te6edf3NotificationTb4b4b4.Te6edf3CategoryTb4b4b4.Te6edf3MeshBeaconTb4b4b4, Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3meshtastic_mesh_beacon_notificationsTb4b4b4)Tb4b4b4,
Te6edf3createChannelTb4b4b4(Te6edf3NotificationTb4b4b4.Te6edf3CategoryTb4b4b4.Te6edf3BatteryTb4b4b4, Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3meshtastic_low_battery_notificationsTb4b4b4)Tb4b4b4,
Te6edf3createChannelTb4b4b4(Te6edf3NotificationTb4b4b4.Te6edf3CategoryTb4b4b4.Te6edf3AlertTb4b4b4, Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3meshtastic_alerts_notificationsTb4b4b4)Tb4b4b4,
Te6edf3createChannelTb4b4b4(Te6edf3NotificationTb4b4b4.Te6edf3CategoryTb4b4b4.Te6edf3ServiceTb4b4b4, Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3meshtastic_service_notificationsTb4b4b4)Tb4b4b4,
Tb4b4b4)
Te6edf3notificationManagerTb4b4b4.Te6edf3createNotificationChannelsTb4b4b4(Te6edf3channelsTb4b4b4)
Te6edf3notificationManagerTb4b4b4.Te6edf3removeLegacyCategoryChannelsTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffcreateChannelTb4b4b4(
Te6edf3categoryTb4b4b4: Te6edf3NotificationTb4b4b4.Te6edf3CategoryTb4b4b4,
Te6edf3nameResTb4b4b4: Te6edf3orgTb4b4b4.Te6edf3jetbrainsTb4b4b4.Te6edf3composeTb4b4b4.Te6edf3resourcesTb4b4b4.Te6edf3StringResourceTb4b4b4,
Tb4b4b4)Tb4b4b4: Te6edf3NotificationChannel Tb4b4b4{
Tff7b72val Te6edf3channelConfig Tff7b72= Te6edf3categoryTb4b4b4.Te6edf3channelConfigTb4b4b4(Tb4b4b4)
Tff7b72return Te6edf3NotificationChannelTb4b4b4(Te6edf3channelConfigTb4b4b4.Te6edf3idTb4b4b4, Te6edf3getStringTb4b4b4(Te6edf3nameResTb4b4b4)Tb4b4b4, Te6edf3channelConfigTb4b4b4.Te6edf3importanceTb4b4b4)
Tb4b4b4}
T8b949e// Keep category-to-channel mapping aligned with MeshNotificationManagerImpl.NotificationType IDs.
Tff7b72private Tff7b72fun Te6edf3NotificationTb4b4b4.Td2a8ffCategoryTb4b4b4.Te6edf3channelConfigTb4b4b4(Tb4b4b4)Tb4b4b4: Te6edf3ChannelConfig Tff7b72= Tff7b72when Tb4b4b4(Tff7b72thisTb4b4b4) Tb4b4b4{
Te6edf3NotificationTb4b4b4.Te6edf3CategoryTb4b4b4.Te6edf3Message Tff7b72-Tff7b72>
Te6edf3ChannelConfigTb4b4b4(
Te6edf3id Tff7b72= Te6edf3NotificationChannelsTb4b4b4.Te6edf3MESSAGESTb4b4b4,
Te6edf3importance Tff7b72= Te6edf3SystemNotificationManagerTb4b4b4.Te6edf3IMPORTANCE_HIGHTb4b4b4,
Tb4b4b4)
Te6edf3NotificationTb4b4b4.Te6edf3CategoryTb4b4b4.Te6edf3NodeEvent Tff7b72-Tff7b72>
Te6edf3ChannelConfigTb4b4b4(
Te6edf3id Tff7b72= Te6edf3NotificationChannelsTb4b4b4.Te6edf3NEW_NODESTb4b4b4,
Te6edf3importance Tff7b72= Te6edf3SystemNotificationManagerTb4b4b4.Te6edf3IMPORTANCE_DEFAULTTb4b4b4,
Tb4b4b4)
Te6edf3NotificationTb4b4b4.Te6edf3CategoryTb4b4b4.Te6edf3MeshBeacon Tff7b72-Tff7b72>
Te6edf3ChannelConfigTb4b4b4(
Te6edf3id Tff7b72= Te6edf3NotificationChannelsTb4b4b4.Te6edf3MESH_BEACONTb4b4b4,
Te6edf3importance Tff7b72= Te6edf3SystemNotificationManagerTb4b4b4.Te6edf3IMPORTANCE_LOWTb4b4b4,
Tb4b4b4)
Te6edf3NotificationTb4b4b4.Te6edf3CategoryTb4b4b4.Te6edf3Battery Tff7b72-Tff7b72>
Te6edf3ChannelConfigTb4b4b4(
Te6edf3id Tff7b72= Te6edf3NotificationChannelsTb4b4b4.Te6edf3LOW_BATTERYTb4b4b4,
Te6edf3importance Tff7b72= Te6edf3SystemNotificationManagerTb4b4b4.Te6edf3IMPORTANCE_DEFAULTTb4b4b4,
Tb4b4b4)
Te6edf3NotificationTb4b4b4.Te6edf3CategoryTb4b4b4.Te6edf3Alert Tff7b72-Tff7b72>
Te6edf3ChannelConfigTb4b4b4(Te6edf3id Tff7b72= Te6edf3NotificationChannelsTb4b4b4.Te6edf3ALERTSTb4b4b4, Te6edf3importance Tff7b72= Te6edf3SystemNotificationManagerTb4b4b4.Te6edf3IMPORTANCE_HIGHTb4b4b4)
Te6edf3NotificationTb4b4b4.Te6edf3CategoryTb4b4b4.Te6edf3Service Tff7b72-Tff7b72>
Te6edf3ChannelConfigTb4b4b4(Te6edf3id Tff7b72= Te6edf3NotificationChannelsTb4b4b4.Te6edf3SERVICETb4b4b4, Te6edf3importance Tff7b72= Te6edf3SystemNotificationManagerTb4b4b4.Te6edf3IMPORTANCE_MINTb4b4b4)
Tb4b4b4}
Tff7b72override Tff7b72suspend Tff7b72fun Td2a8ffdispatchTb4b4b4(Te6edf3notificationTb4b4b4: Te6edf3NotificationTb4b4b4)Tb4b4b4: Tffa657Boolean Tb4b4b4{
Te6edf3ensureChannelsInitializedTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3channelId Tff7b72= Te6edf3notificationTb4b4b4.Te6edf3categoryTb4b4b4.Te6edf3channelConfigTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3id
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3canPostNotificationsTb4b4b4(Te6edf3channelIdTb4b4b4)Tb4b4b4) Tff7b72return Tff7b72false
Tff7b72val Te6edf3id Tff7b72= Te6edf3notificationTb4b4b4.Te6edf3id Tff7b72?: Te6edf3notificationTb4b4b4.Te6edf3hashCodeTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3builder Tff7b72=
Te6edf3NotificationCompatTb4b4b4.Te6edf3BuilderTb4b4b4(Te6edf3contextTb4b4b4, Te6edf3channelIdTb4b4b4)
Tb4b4b4.Te6edf3setContentTitleTb4b4b4(Te6edf3notificationTb4b4b4.Te6edf3titleTb4b4b4)
Tb4b4b4.Te6edf3setContentTextTb4b4b4(Te6edf3notificationTb4b4b4.Te6edf3messageTb4b4b4)
Tb4b4b4.Te6edf3setSmallIconTb4b4b4(Te6edf3drawableTb4b4b4.Te6edf3meshtastic_ic_notificationTb4b4b4)
Tb4b4b4.Te6edf3setAutoCancelTb4b4b4(Tff7b72trueTb4b4b4)
Tb4b4b4.Te6edf3setSilentTb4b4b4(Te6edf3notificationTb4b4b4.Te6edf3isSilentTb4b4b4)
Te6edf3notificationTb4b4b4.Te6edf3groupTff7b72?.Te6edf3let Tb4b4b4{ Te6edf3builderTb4b4b4.Te6edf3setGroupTb4b4b4(Tffa657itTb4b4b4) Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3notificationTb4b4b4.Te6edf3type Tff7b72=Tff7b72= Te6edf3NotificationTb4b4b4.Te6edf3TypeTb4b4b4.Te6edf3ErrorTb4b4b4) Tb4b4b4{
Te6edf3builderTb4b4b4.Te6edf3setPriorityTb4b4b4(Te6edf3NotificationCompatTb4b4b4.Te6edf3PRIORITY_HIGHTb4b4b4)
Tb4b4b4}
Te6edf3notificationTb4b4b4.Te6edf3deepLinkUriTff7b72?.Te6edf3let Tb4b4b4{ Te6edf3uri Tff7b72-Tff7b72> Te6edf3builderTb4b4b4.Te6edf3setContentIntentTb4b4b4(Te6edf3createDeepLinkPendingIntentTb4b4b4(Te6edf3uriTb4b4b4, Te6edf3idTb4b4b4)Tb4b4b4) Tb4b4b4}
Tff7b72return Tff7b72try Tb4b4b4{
Te6edf3notificationManagerTb4b4b4.Te6edf3notifyTb4b4b4(Te6edf3idTb4b4b4, Te6edf3builderTb4b4b4.Te6edf3buildTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72true
Tb4b4b4} Tff7b72catch Tb4b4b4(Te6edf3_Tb4b4b4: Te6edf3SecurityExceptionTb4b4b4) Tb4b4b4{
Tff7b72false
Tb4b4b4}
Tb4b4b4}
Tff7b72private Tff7b72fun Td2a8ffcanPostNotificationsTb4b4b4(Te6edf3channelIdTb4b4b4: Tffa657StringTb4b4b4)Tb4b4b4: Tffa657Boolean Tff7b72=
Te6edf3NotificationManagerCompatTb4b4b4.Te6edf3fromTb4b4b4(Te6edf3contextTb4b4b4)Tb4b4b4.Te6edf3areNotificationsEnabledTb4b4b4(Tb4b4b4) Tff7b72&Tff7b72&
Tb4b4b4(
Te6edf3BuildTb4b4b4.Te6edf3VERSIONTb4b4b4.Te6edf3SDK_INT Tff7b72< Te6edf3BuildTb4b4b4.Te6edf3VERSION_CODESTb4b4b4.Te6edf3O Tff7b72|Tff7b72|
Te6edf3notificationManagerTb4b4b4.Te6edf3getNotificationChannelTb4b4b4(Te6edf3channelIdTb4b4b4)Tff7b72?.Te6edf3importance Tff7b72!Tff7b72=
Te6edf3SystemNotificationManagerTb4b4b4.Te6edf3IMPORTANCE_NONE
Tb4b4b4)
T8b949e/**
* Builds a [PendingIntent] that launches [MainActivity] with the given deep-link URI as [Intent.ACTION_VIEW], so
* the existing deep-link plumbing (`UIViewModel.handleDeepLink` → `DeepLinkRouter` → `MultiBackstack`) can
* synthesize the proper backstack and surface the target screen.
*
* Uses [Class.forName] to avoid pulling the `:androidApp` module into `:core:service` as a Gradle dep.
*/
Tff7b72private Tff7b72fun Td2a8ffcreateDeepLinkPendingIntentTb4b4b4(Te6edf3uriTb4b4b4: Tffa657StringTb4b4b4, Te6edf3requestCodeTb4b4b4: Tffa657IntTb4b4b4)Tb4b4b4: Te6edf3PendingIntent Tb4b4b4{
Tff7b72val Te6edf3deepLinkIntent Tff7b72=
Te6edf3IntentTb4b4b4(Te6edf3IntentTb4b4b4.Te6edf3ACTION_VIEWTb4b4b4, Te6edf3uriTb4b4b4.Te6edf3toUriTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3contextTb4b4b4, Te6edf3ClassTb4b4b4.Te6edf3forNameTb4b4b4(Te6edf3MAIN_ACTIVITY_CLASSTb4b4b4)Tb4b4b4)Tb4b4b4.Te6edf3apply Tb4b4b4{
Te6edf3flags Tff7b72= Te6edf3IntentTb4b4b4.Te6edf3FLAG_ACTIVITY_SINGLE_TOP
Tb4b4b4}
Tff7b72return Te6edf3TaskStackBuilderTb4b4b4.Te6edf3createTb4b4b4(Te6edf3contextTb4b4b4)Tb4b4b4.Te6edf3run Tb4b4b4{
Te6edf3addNextIntentWithParentStackTb4b4b4(Te6edf3deepLinkIntentTb4b4b4)
Te6edf3getPendingIntentTb4b4b4(Te6edf3requestCodeTb4b4b4, Te6edf3PendingIntentTb4b4b4.Te6edf3FLAG_IMMUTABLE Te6edf3or Te6edf3PendingIntentTb4b4b4.Te6edf3FLAG_UPDATE_CURRENTTb4b4b4)Tff7b72!!
Tb4b4b4}
Tb4b4b4}
Tff7b72override Tff7b72fun Td2a8ffcancelTb4b4b4(Te6edf3idTb4b4b4: Tffa657IntTb4b4b4) Tb4b4b4{
Te6edf3notificationManagerTb4b4b4.Te6edf3cancelTb4b4b4(Te6edf3idTb4b4b4)
Tb4b4b4}
Tff7b72override Tff7b72fun Td2a8ffcancelAllTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3notificationManagerTb4b4b4.Te6edf3cancelAllTb4b4b4(Tb4b4b4)
Tb4b4b4}
Tff7b72private Tff7b72companion Tff7b72object Tb4b4b4{
T8b949e/**
* Fully-qualified name of the host activity that handles `meshtastic://` deep-link intents. Kept as a string to
* avoid creating a module dependency from `:core:service` back onto `:androidApp`.
*/
Tff7b72const Tff7b72val Te6edf3MAIN_ACTIVITY_CLASS Tff7b72= Ta5d6ff"Ta5d6fforg.meshtastic.app.MainActivityTa5d6ff"
Tb4b4b4}
Tb4b4b4}
Served by rngit 1.5.0 - Generated in 0.06s